package keye.document_manage.interceptor;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;

import keye.document_manage.entity.Page;
import keye.document_manage.util.MultipleDataSource;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

/**
 * 分页拦截器
 */
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})
public class PageInterceptor implements Interceptor {
	
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
		MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
		//MetaObject metaObject = MetaObject.forObject(statementHandler,  SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
		MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");
		
		// 配置文件中SQL语句的ID
		String id = mappedStatement.getId();
		if(id.matches(".+ByPage$")) {
			BoundSql boundSql = statementHandler.getBoundSql();
			Map<?,?> parameter = (Map<?,?>)boundSql.getParameterObject();
			Page page = (Page)parameter.get("page");
			if(null == page){
				return invocation.proceed();
			}
			// 原始的SQL语句
			String sql = boundSql.getSql();
			// 查询总条数的SQL语句
			//sql.replaceAll("order by || group by", "");
			//如果有order by等sqlserver会提示：“除非另外还指定了 TOP 或 FOR XML，否则，ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效” 的错误。
			sql = sql.toLowerCase();
			String countSql = "select count(*) from (" + sql.replaceAll("order by.*|group by.*", "") + ") a";
			Connection connection = (Connection)invocation.getArgs()[0];
			PreparedStatement countStatement = connection.prepareStatement(countSql);
			ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");
			parameterHandler.setParameters(countStatement);
			ResultSet rs = countStatement.executeQuery();
			
			if(rs.next()) {
				page.setTotalNumber(rs.getInt(1));
			}
			
			metaObject.setValue("delegate.boundSql.sql", sqlpage(sql, page.getDbIndex(), page.getDbNumber()));
		}
		return invocation.proceed();
	}

	// 获取分页查询的SQL语句
	public String sqlpage(String sql, long dbIndex, long dbNumber){
		return MultipleDataSource.getDialect().getPageSql(sql, dbIndex, dbNumber);
	}
	
	@Override
	public Object plugin(Object target) {
		if (target instanceof StatementHandler) {  
	        return Plugin.wrap(target, this);  
	    } else {  
	        return target;  
	    }  
	}

	@Override
	public void setProperties(Properties properties) {
		
	}

}
